﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;



namespace InstaGM
{

    public partial class Form1 : Form
    {
        //Define tool wide variables
        public TcpClient tcpc;
        public NetworkStream ns;
        public Regex objToMatch { get; set; }
        public string ret { get; set; }
        public Byte[] output = new Byte[1024];
        public String responseoutput = String.Empty;
        public Byte[] cmd = System.Text.Encoding.ASCII.GetBytes("\n");
        public string cmd_txt { get; set; }
        public bool cmd_issued { get; set; }
        public bool ins_sum_issued { get; set; }
        public bool raw_cmd_issued { get; set; }
        public bool pass_sent { get; set; }
        public bool char_focus_requested { get; set; }
        public bool char_focused { get; set; }
        public static string host_val = Properties.Settings.Default.host;
        public static int port_val = Properties.Settings.Default.port;
        public static string pass_val = Properties.Settings.Default.pass;
        //Define Telecaster settings
        public static string db_name = Properties.Settings.Default.db_name;
        public static string db_user = Properties.Settings.Default.db_user;
        public static string db_pass = Properties.Settings.Default.db_pass;
        bool auto_connect = Properties.Settings.Default.auto_conn;
        public bool auto_tamed = Properties.Settings.Default.auto_tamed;
        bool first_time = Properties.Settings.Default.first_time;
        bool states_to_telnet = Properties.Settings.Default.to_telnet;
        bool states_to_clipboard = Properties.Settings.Default.state_to_clipboard;
        SqlDataAdapter adapter = new SqlDataAdapter();
        public static string connectionString = "server="+host_val+";database="+db_name+";user id="+db_user+";password="+db_pass+";Trusted_Connection=no;Timeout=10;"; 
        public DataSet job_list = new DataSet();
        public BackgroundWorker bgw = new BackgroundWorker();
        public string tmp_job_name { get; set; }
        public int new_job_id { get; set; }
        public int char_sid { get; set; }
        public string char_name { get; set; }
        public string acc_name { get; set; }
        public int acc_id { get; set; }
        public string tmp = Directory.GetCurrentDirectory();
        public int insert_summon_id { get; set; }
        public Assembly Asm;
        public StreamReader summon_list;
        public StreamReader item_list;
        public StreamReader state_list;
        public int items_read;
        public int chars_read;
        public int summons_read;
        public int states_read;

        public Form1()
        {
            InitializeComponent();
            //These are for various clicked performed throughout InstaGM
            AddControlEvent();
        }


        //Upon the program loading these things will occur
        private void Form1_Load(object sender, EventArgs e)
        {
            //We have to try to load the embedded resources 
            //Just incase the lists are not present in physical folder
	        try
            {
                //Define the Assembly
                Asm = Assembly.GetExecutingAssembly();
                //Define the embedded resources
                summon_list = new StreamReader(Asm.GetManifestResourceStream("InstaGM.summon_list.txt"));
                item_list = new StreamReader(Asm.GetManifestResourceStream("InstaGM.item_list.txt"));
                state_list = new StreamReader(Asm.GetManifestResourceStream("InstaGM.state_list.txt"));
            }
            catch
            {
                //If any resources fail to load
                MessageBox.Show("Error accessing resources!");
            }
	
            //If this is the first time this program has been loaded
            if (first_time == true)
            {
                //Show first time informational dlg
                first_time first_dlg = new first_time();
                //Show it as dialog so it must be closed before the user can continue
                first_dlg.ShowDialog();          
            }

            //Load the Character List
            load_characters();

            //If user has defined Auto-Connect 
            if (auto_connect == true)
            {
                button1_Click(connect_btn, EventArgs.Empty);   
            }

            //Set Ite/Buff Box Instructional Tooltip
            ToolTip tooltip = new ToolTip();
            tooltip.ToolTipIcon = ToolTipIcon.Info;
            tooltip.ToolTipTitle = "Information";
            tooltip.IsBalloon = true;
            tooltip.ShowAlways = true;
            tooltip.AutoPopDelay = 500000000;
            tooltip.SetToolTip(item_grid_q, "The Item Panel is designed entirely with the user in mind.\n\nOnce you have clicked the item tab the loading process has already begun!\n\nYou can now begin searching for your item! How? Simply, scroll up/down or type an item name in the Search Box\n\nSearch Box Notes: The search box will highlight the closest result in the item list as you type it, to reset your search just blank the text by pressing backspace or alt+a then backspace.\n\nOnce you have found the item you desire, set it's # and lv/+ when applicable (lv and + are only applicable when sending Items to Clip Board)\n\nNow just click the \"Insert\" Button!");
            tooltip.SetToolTip(state_grid_q, "The Buff Panel is designed entirely with the user in mind.\n\nOnce you have clicked the buff tab the loading process has already begun!\n\nYou can now begin searching for your buff! How? Simply scroll up/down or type a buff name in the Search Box\n\nSearch Box Notes: The search box will highlight the closest result in the buff list as you type it, to reset your search just blank the text by pressing backspace or alt+a then backspace.\n\nOnce you have found the buff you desire, edit it's lv and then double click it!");
        }

        //Connect button is pressed
        private void button1_Click(object sender, EventArgs e)
        {
            //Below we will try to define a new TCP Client to use for our Telnet communications
            try
            {
                //Define Telnet Client
                tcpc = new TcpClient(host_val, port_val);

                //Define the fetched Telnet Stream
                ns = tcpc.GetStream();
                //Define a new background worker
                bgw = new BackgroundWorker();
                //Define what the background worker will do
                bgw.DoWork += exec_conn;
                //Begin background worker to execute connection asynchronously
                bgw.RunWorkerAsync();
            }
            catch (Exception)
            {
                //If unable to connect we should display a message
                MessageBox.Show("Connection Failed!\n\nNon-Remote Setup:\n- Set Host to 127.0.0.1/Localhost\n- Set Port same as S console.port (in gameserver opt)\n\nRemote Setup:\n!!IMPORTANT!! Make sure the following has been done on the remote server:\n\n- S console.port is opened in both Windows Firewall and Router (if applicable)\n- S console._password has been set");
            }
        }

        //Execute the connect function if status is not idle (already connected)
        public void exec_conn(object sender, DoWorkEventArgs e)
        {
            if (status.Text == "Idle")
            {
                MessageBox.Show("Telnet is already connected");
            }
                else
            {
                //Connect to Telnet
                connect(Properties.Settings.Default.pass);  
            }
        }

        //Execute the sendcommand function 
        public void exec_send(object sender, DoWorkEventArgs e)
        {
           sendcommand(command.Text);          
        }

        //Open Settings Menu
        private void dBSettingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            instagm_settings dbs = new instagm_settings();
            dbs.ShowDialog();
        }

        //Add Character to Character List
        private void button2_Click(object sender, EventArgs e)
        {
            //If Character name is not null or empty
            if (string.IsNullOrEmpty(character_name.Text))
            {
                MessageBox.Show("You must enter a player name first", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
            else
            {
                //Name is not empty, so let's add it to the list
                char_list.Items.Add(character_name.Text);
                //Using a stream writer
                using (TextWriter streamWriter = new StreamWriter(File.Create(Path.Combine(this.tmp, "character_list.txt"))))
                {
                    foreach (string item in char_list.Items)
                    {
                        //let's write each name in the character list
                        streamWriter.WriteLine(item);
                    }
                }
            }
        }

        //Remove Character from Character List
        private void button3_Click(object sender, EventArgs e)
        {
            //Try to remove the item
            try
            {
                //If there is no character selected
                if (char_list.SelectedIndex == -1)
                {
                    MessageBox.Show("You must select a player name first!");
                }
                else
                {
                    //Character was selected, lets remove him frm the list
                    char_list.Items.RemoveAt(char_list.SelectedIndex);
                    //using a textwriter 
                    using (TextWriter streamWriter = new StreamWriter(File.Create(Path.Combine(this.tmp, "character_list.txt"))))
                    {
                        //For each name on the list we will write to the file
                        foreach (string item in char_list.Items)
                        {
                            streamWriter.WriteLine(item);
                        }
                    }
                }
            }
            catch
            {
                MessageBox.Show("Unexpected Error during deletion!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }

        //Insert Gold
        private void button4_Click(object sender, EventArgs e)
        {
            if (char_list.SelectedIndex == -1)
            {
                MessageBox.Show("Please select a player first!");
            }
            else
            {
                if (status.Text == "Idle")
                {
                    if (gold.Text != "")
                    {
                        cmd_txt = "#insert_gold(\""+gold.Text+"\","+"\""+char_list.SelectedItem.ToString()+"\")";
                        sendcommand(cmd_txt);
                    }
                }
                else
                {
                    MessageBox.Show("Playername Set, Telet Not Connected");
                }
            }
        }

        //Set Value
        private void button5_Click(object sender, EventArgs e)
        {
            if (set_val_list.SelectedIndex == -1)
            {
                MessageBox.Show("Please select a value to be set first!");
            }
            else
            {
                if (status.Text == "Idle")
                {
                    if (!string.IsNullOrEmpty(set_val_val.Text))
                    {
                        if (set_val_list.SelectedItem.ToString() == "hp" || set_val_list.SelectedItem.ToString() == "mp" || set_val_list.SelectedItem.ToString() == "lv" || set_val_list.SelectedItem.ToString() == "tp" || set_val_list.SelectedItem.ToString() == "permission")
                        {
                            cmd_txt = "#set_value(\"" + set_val_list.SelectedItem.ToString() + "\"," + "\"" + set_val_val.Text + "\"," + "\"" + char_list.SelectedItem.ToString() + "\")";
                        }
                        sendcommand(cmd_txt);
                    }
                }
                else
                {
                    MessageBox.Show("Telnet Not Connected!");
                }
            }
        }

        //Change Job
        private void button6_Click(object sender, EventArgs e)
        {
            if (job_name.SelectedIndex == -1)
            {
                MessageBox.Show("Please select a value to be set first!");
            }
            else
            {
                if (status.Text == "Idle")
                {
                    string j = "job";
                    if (char_list.SelectedIndex == -1)
                    {
                        MessageBox.Show("You must Select a Player Name First!");
                    }
                    else
                    {
                        new_job_id = get_job_id(job_name.SelectedItem.ToString());
                        cmd_txt = "#set_value(\"" + j + "\"," + "\"" + new_job_id.ToString() + "\"," + "\"" + char_list.SelectedItem.ToString() + "\")";
                        sendcommand(cmd_txt);
                    }
                }
                else
                {
                    MessageBox.Show("Telnet is not connected!");
                }
            }
        }

        //Learn All Skill
        private void button7_Click(object sender, EventArgs e)
        {
            if (status.Text == "Idle")
            {
                if (char_list.SelectedIndex == -1)
                {
                    MessageBox.Show("You must select a player name first!");
                }
                else
                {
                    cmd_txt = "#learn_all_skill(\"" + char_list.SelectedItem.ToString() + "\")";
                    sendcommand(cmd_txt);
                }
            }
            else
            {
                MessageBox.Show("Telnet not connected!");
            }
        }

        //Kick Player
        private void button10_Click(object sender, EventArgs e)
        {
            if (status.Text == "Idle")
            {
                if (char_list.SelectedIndex == -1)
                {
                    MessageBox.Show("You must select a player name first!");
                }
                else
                {
                    cmd_txt = "#kick(\"" + char_list.SelectedItem.ToString() + "\")";
                    sendcommand(cmd_txt);
                }
            }
            else
            {
                MessageBox.Show("Telnet not connected!");
            }
        }

        //Learn Creature All Skill
        private void button8_Click(object sender, EventArgs e)
        {
            if (status.Text == "Idle")
            {
                if (char_list.SelectedIndex == -1)
                {
                    MessageBox.Show("You must select a player name first!");
                }
                else
                {
                    cmd_txt = "#learn_creature_all_skill(\"" + char_list.SelectedItem.ToString() + "\")";
                    sendcommand(cmd_txt);
                }
            }
            else
            {
                MessageBox.Show("Telnet not connected!");
            }
        }

        //Mute Player
        private void button9_Click(object sender, EventArgs e)
        {
            if (status.Text == "Idle")
            {
                if (char_list.SelectedIndex == -1)
                {
                    MessageBox.Show("You must select a player name first!");
                }
                else
                {
                    if (mute_time_val.Text != "")
                    {
                        double fin_time_val = 0;

                        if (mute_time_type.Text != "")
                        {
                            if (mute_time_type.Text == "min")
                            {
                                fin_time_val = TimeSpan.FromMinutes(Convert.ToInt32(mute_time_val.Text)).TotalSeconds;
                            }
                            if (mute_time_type.Text == "hour")
                            {
                                fin_time_val = TimeSpan.FromHours(Convert.ToInt32(mute_time_val.Text)).TotalSeconds;
                            }
                            if (mute_time_type.Text == "day")
                            {
                                fin_time_val = TimeSpan.FromDays(Convert.ToInt32(mute_time_val.Text)).TotalSeconds;
                            }
                            cmd_txt = "#block_chat "+char_list.SelectedItem.ToString()+" "+fin_time_val+"";
                            sendcommand(cmd_txt);
                        }
                    }
                }
            }
            else
            {
                MessageBox.Show("Telnet not connected!");
            }
        }

        //Summon Grid Clicked
        private void dataGridView1_Click(object sender, EventArgs e)
        {
            if (status.Text == "Idle")
            {
                if (char_list.SelectedIndex == -1)
                {
                    MessageBox.Show("You must select a player name first!");
                }
                else 
                {
                    DataGridViewRow row = summon_grid.CurrentCell.OwningRow;
                    int returned_val = Convert.ToInt32(row.Cells["summon_id"].Value);
                    insert_summon_id = returned_val;

                    if (tamed.Checked == true)
                    {
                        if (Properties.Settings.Default.item_to_itembox == true)
                        {
                            if (MessageBox.Show("You can not send tamed pets to the Item Box!\n\nWould you like to send to Clip Board instead?", "Warning", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                            {
                                string clip_cmd = "/run insert_item(\"" + insert_summon_id + "\", 1,0,0,2, \"" + char_list.SelectedItem + "\")";
                                this.Invoke(new MethodInvoker(delegate { status.Text = "Working"; }));
                                sendtoclip(clip_cmd);
                            }
                        }
                        if (Properties.Settings.Default.item_to_clipboard == true)
                        {
                            string clip_cmd = "/run insert_item(\"" + insert_summon_id + "\", 1,0,0,2, \"" + char_list.SelectedItem + "\")";
                            this.Invoke(new MethodInvoker(delegate { status.Text = "Working"; }));
                            sendtoclip(clip_cmd);
                        }
                    }
                    else //Tamed NOT Checked
                    {
                        if (Properties.Settings.Default.item_to_itembox == true)
                        {
                            insert_summon();
                        }
                        if (Properties.Settings.Default.item_to_clipboard == true)
                        {
                            string clip_cmd = "/run insert_item(\"" + insert_summon_id + "\", 1,0,0,2, \"" + char_list.SelectedItem + "\")";
                            sendtoclip(clip_cmd);
                        }
                    }
                }
            }
        }

        //Item Grid Clicked
        private void insert_item_Click(object sender, EventArgs e)
        {
            if (char_list.SelectedIndex == -1)
            {
                MessageBox.Show("You must selected a player name first!");
            }
            else
            {
                //INSERT_ITEM
                insert_item();
            }
        }

        //Removeable state_grid_cell is clicked
        private void state_grid_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
        }

        //State Grid is Double Clicked
        private void state_grid_insert(object sender, EventArgs e)
        {
            if (char_list.SelectedIndex == -1)
            {
                MessageBox.Show("You must selected a player name first!");
            }
            else
            {
                //INSERT_STATE
                insert_state();
            }
        }

    }
}
